﻿using RabbitMQ.Client.Events;
using RabbitMQ.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp5
{
    public class Comprehensive
    {
        // 设置最大重试次数
        private static int maxRetryCount = 3;
        public static void Consume(string[] args)
        {
            var factory = new ConnectionFactory { HostName = "supplier.xl24h.cn", Port = 5672, UserName = "admin", Password = "das@123!", VirtualHost = "/" };
            using var connection = factory.CreateConnection();
            using (var channel = connection.CreateModel())
            {
                // 设置队列参数，这里仅为了示例重新声明，实际应用中不需要重复声明
                var arguments = new Dictionary<string, object>
        {
            {"x-dead-letter-exchange", "dead_letter_exchange"},
            {"x-dead-letter-routing-key", "dead_letter_routing_key"},
            {"x-message-ttl", 5000} // 设置重试间隔为 5 秒
        };
                channel.QueueDeclare("retry_queue", durable: true, exclusive: false, autoDelete: false, arguments: arguments);

                // 设置消费相关参数
                var consumer = new EventingBasicConsumer(channel);
                consumer.Received += (model, ea) =>
                {
                    var body = ea.Body.ToArray();
                    var message = Encoding.UTF8.GetString(body);
                    var retryCount = 0;

                    // 尝试从消息属性中获取重试次数
                    if (ea.BasicProperties.Headers != null && ea.BasicProperties.Headers.ContainsKey("x-retry-count"))
                    {
                        retryCount = (int)ea.BasicProperties.Headers["x-retry-count"];
                    }

                    Console.WriteLine($"Received message: '{message}', Retry count: {retryCount}");

                    try
                    {
                        // 模拟消息处理
                        ProcessMessage(message);

                        // 如果消息处理成功，则确认消息
                        channel.BasicAck(ea.DeliveryTag, multiple: false);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"Error processing message: {ex.Message}");

                        // 如果达到最大重试次数，则拒绝消息，使其进入死信队列
                        if (retryCount >= maxRetryCount)
                        {
                            channel.BasicReject(ea.DeliveryTag, requeue: false);
                            Console.WriteLine("Message sent to dead letter queue.");
                        }
                        else
                        {
                            // 否则，更新重试次数，并将消息重新入队
                            retryCount++;
                            var basicProperties = ea.BasicProperties;
                            basicProperties.Headers = basicProperties.Headers ?? new Dictionary<string, object>();
                            basicProperties.Headers["x-retry-count"] = retryCount;

                            channel.BasicPublish("retry_exchange", "retry_routing_key", basicProperties, body);
                            Console.WriteLine("Message requeued for retry.");

                            // 确认原始消息，因为我们已经手动重新入队了
                            channel.BasicAck(ea.DeliveryTag, multiple: false);
                        }
                    }
                };

                // 开始消费消息
                channel.BasicConsume(queue: "retry_queue", autoAck: false, consumer: consumer);

                Console.WriteLine("Consumer started. Press [enter] to exit.");
                Console.ReadLine();
            }
        }

        // 模拟消息处理方法
        private static void ProcessMessage(string message)
        {
            // 这里应该包含实际的消息处理逻辑
            // 为了示例，我们随机抛出异常来模拟处理失败
            var random = new Random();
            // 20% 的概率抛出异常
            if (random.Next(1, 5) == 1)
            {
                throw new Exception("Failed to process message.");
            }
        }
    }
}
